import {
    Vector2,
    Box2,
    Shape,
    Mesh,
    LineLoop,
    BufferGeometry,
    BoxGeometry,
    BoxBufferGeometry,
    PlaneGeometry,
    ShapeGeometry,
    ExtrudeGeometry,
    LineBasicMaterial,
    MeshPhongMaterial,
    MeshLambertMaterial,
    // TextureLoader,
    DoubleSide,
    Color,
    // LinearFilter,
    // RepeatWrapping,
} from 'three'
import { mixinMapObject } from './map-object'
import { parsePoints } from '../utils/view'
import Label from './label'

class Room extends Mesh {
    constructor(floor, attr = {}) {
        super()
        this.floor = floor
        this.info = attr
        let { name } = attr
        this.name = name
        this.info.height = this.info.height || this.floor.info.height

        this.initObject3D()

        if (name !== "中空区域") {
          this.onHover = (hovered) => {
            // console.log("onHover hovered=" + hovered + " " + this.name);
            if (this.selected) return;
            if (hovered) {
              this.material.color.multiplyScalar(0.8);
            } else {
              this.material.setValues({color: this.origColor});
            }
      
            this.$map && this.$map.forceUpdate();
          }
      
          this.onSelect = (selected) => {
            // console.log("onSelect selected=" + selected);
            this.selected = selected;
            if (selected) {
              this.material.setValues({color: this.selectedColor});
            } else {
              this.material.setValues({color: this.origColor});
            }
      
            this.$map && this.$map.forceUpdate();
          }
        }
    }

    initObject3D() {
        let points = parsePoints(this.info.outline[0][0])
        let shape = new Shape(points)

        let extrudeSettings = {
            depth: this.info.height,
            bevelEnabled: false,
        }
        let geometry3d = new ExtrudeGeometry(shape, extrudeSettings)
        let geometry2d = new ShapeGeometry(shape)
        this.geometry = geometry3d
        this.material = new MeshLambertMaterial()
        this.origColor = this.material.color.clone();
        this.selectedColor = this.material.color.clone().multiplyScalar(0.5);
        this.selected = false;
        // this.material.alphaTest = 0.1
        this.onViewModeChange = is3dMode => {
          this.geometry = is3dMode ? geometry3d : geometry2d
          this.position.setZ(is3dMode ? 0 : 1)
        }
        this.renderOrder = 2
        this.type = 'Room'
        let box = new Box2()

        if (this.info.walls) {
            this.material.opacity = 0
            this.material.alphaTest = 0.1
            // let geometry = new ShapeGeometry(shape)
            // let groundMaterial = new MeshPhongMaterial()
            // let textureLoader = new TextureLoader()
            // textureLoader.load('./textures/floor-board.jpg', function(texture) {
            //     texture.minFilter = LinearFilter
            //     texture.wrapS = RepeatWrapping
            //     texture.wrapT = RepeatWrapping
            //     texture.anisotropy = 16
            //     texture.repeat.set(0.01, 0.01)
            //     groundMaterial.needsUpdate = true
            //     groundMaterial.map = texture
            // })
            // mesh = new Mesh(geometry, groundMaterial)
            // mesh.position.set(0, 0, 1)
            // object.add(mesh)
            let material = new MeshPhongMaterial({
                color: 0x156289,
                emissive: 0x072534,
                side: DoubleSide,
                flatShading: true,
                opacity: 0.5,
                transparent: true,
                alphaTest: 0.1,
            })
            this.info.walls.forEach(wall => {
                let wallPoints = parsePoints(wall)
                let geometry3d = new BoxGeometry(5, wallPoints[0].distanceTo(wallPoints[1]), this.floor.info.height)
                let geometry2d = new PlaneGeometry(5, wallPoints[0].distanceTo(wallPoints[1]))
                let cube = new Mesh(geometry3d, material)
                cube.position.set(
                    (wallPoints[0].x + wallPoints[1].x) / 2,
                    (wallPoints[0].y + wallPoints[1].y) / 2,
                    this.floor.info.height / 2
                )
                cube.rotation.z = wallPoints[0].sub(wallPoints[1]).angle() + (Math.PI * 3) / 2
                cube.onViewModeChange = is3dMode => {
                    cube.geometry = is3dMode ? geometry3d : geometry2d
                    cube.position.setZ(is3dMode ? this.floor.info.height / 2 : 2)
                }
                cube.renderOrder = 3
                this.add(cube)
            })
        } else {
            let geometry = new BufferGeometry().setFromPoints(points)
            let wire = new LineLoop(geometry)
            wire.material = new LineBasicMaterial()
            wire.material.alphaTest = 0.1
            wire.position.set(0, 0, this.floor.info.height)
            wire.onViewModeChange = is3dMode => wire.position.setZ(is3dMode ? this.info.height : 2)
            this.add(wire)
            wire.renderOrder = 3
            this.onThemeChange = theme => {
                let roomStyle = theme.roomStyle[this.info.category] || theme.roomStyle['default'] 
                this.material.setValues(roomStyle)
                this.origColor = this.material.color.clone();
                if (theme.selected === 'auto') {
                  this.selectedColor = this.origColor.clone().multiplyScalar(0.5);
                } else {
                  this.selectedColor = new Color(theme.selected);
                }
                wire.material.setValues(roomStyle)
                wire.material.color.multiplyScalar(0.8)
            }
            this.wireMaterial = wire.material;
        }
        if (this.info.pillars) {
            let material = new MeshLambertMaterial({
                color: 0xffffff,
                emissive: 0x555555,
            })
            let center = new Vector2(),
                size = new Vector2()
            this.info.pillars.forEach(pillar => {
                let pillarPoints = parsePoints(pillar)
                box.setFromPoints(pillarPoints).getCenter(center)
                box.getSize(size)
                let geometry3d = new BoxBufferGeometry(size.width, size.height, this.info.height)
                let geometry2d = new PlaneGeometry(size.width, size.height)
                let cube = new Mesh(geometry3d, material)
                cube.position.set(center.x, center.y, this.info.height / 2)
                cube.onViewModeChange = is3dMode => {
                    cube.geometry = is3dMode ? geometry3d : geometry2d
                    cube.position.setZ(is3dMode ? this.info.height / 2 : 2)
                }
                cube.renderOrder = 3
                this.add(cube)
            })
        }

        let sprite = new Label(this.info.name)
        if (sprite) {
            sprite.onThemeChange = theme => {
                let material = theme.materialMap.get(this.info.category + '')
                sprite.setOptions(theme.fontStyle)
                if (!material || !material.map) {
                    sprite.setIcon()
                } else {
                    material.depthTest = false
                    sprite.setIcon({ icon: material.map })
                }
                sprite.needsUpdate = true
            }
            let center = box.setFromPoints(points).getCenter(new Vector2())
            sprite.position.set(center.x, center.y, this.floor.info.height + 5)
            sprite.center.set(0.5, 0)
            // sprite.renderOrder = 10
            sprite.onViewModeChange = is3dMode => sprite.position.setZ(is3dMode ? this.floor.info.height + 5 : 3)
            this.add(sprite)
            sprite.renderOrder = 99
            this.label = sprite
        }
    }

    setToolTip(tipInfo) {
      if (this.label) {
        this.label.tipInfo = tipInfo;
        this.label.needsUpdate = true;
      }
    }
}

mixinMapObject(Room)

Object.defineProperties(Room.prototype, {
    isRoom: {
        configurable: false,
        writable: false,
        value: true,
    },
})

export default Room
